<?php


namespace app\cms\community\lib\utils;


class nodeSortByGroup
{
    // 排序后的数组
    protected array $sortNode = [];

    /**
     * nodeSortByGroup constructor.
     * @param array $node 需要排序的数组
     * @param string $nodeParentKey 父节点key
     * @param string $nodeKey
     * @param string|int $nodeParentValue 当节点值等于这个时为父节点
     */
    public function __construct(
        protected array $node,
        protected string $nodeKey = 'id',
        protected string $nodeParentKey = 'parent_id',
        protected string|int $nodeParentValue = 0
    ) {}


    /**
     * 开始排序
     * @return static
     */
    public function sort(): static {
        if ($this->sortNode) return $this;
        $this->sortNode = $this->setRootNode()
            -> setChildrenNode($this->sortNode);

        return $this;
    }

    /**
     * 获取根节点
     * @return $this
     */
    protected function setRootNode(): static {
        array_walk($this->node, function ($value, $key) {
            if ($value[$this->nodeParentKey] == $this -> nodeParentValue) {
                $value['children'] = [];
                $this->sortNode[] = $value;
                unset($this->node[$key]);
            }
        });
        return $this;
    }

    /**
     * 子节点分组
     * @param array $node
     * @return array
     */
    protected function setChildrenNode(array $node): array {
        if (!$node) return [];
        foreach ($node as $nodeKey => $nodeValue) {
            foreach ($this->node as $nKey => $nValue) {
                if ($nodeValue[$this -> nodeKey] == $nValue[$this -> nodeParentKey]) {
                    $nValue['children'] = [];
                    $nodeValue['children'][] = $nValue;
                    unset($this->node[$nKey]);
                }
            }

            if ($nodeValue['children']) {
                $nodeValue['children'] = $this->setChildrenNode($nodeValue['children']);
            }
        }
        return $node;
    }

    /**
     * 追加节点
     * @param array $node
     * @return $this
     */
    public function addNode(array $node): static
    {
        if ($node[$this->nodeParentKey] == $this->nodeParentValue) {
            $this->sortNode[] = $this->node;
            return $this;
        }

        $this->node[] = $node;
        $this->sortNode = $this -> setChildrenNode($this -> sortNode);
        return $this;
    }

    /**
     * 获取节点数据
     * @param string|int $nodeId
     * @param bool $remove 获取节点并删除
     * @return array
     */
    public function getNode(string|int $nodeId, bool $remove = false): array
    {
        // 遍历节点
        foreach ($this->sortNode as $nodeKey => &$nodeValue) {
            if ($nodeValue[$this->nodeKey] === $nodeId) {
                if ($remove) unset($this->sortNode[$nodeKey]);
                return $nodeValue;
            }

            if ($value = $this->getChildrenNodeById($nodeId, $nodeValue['children'], $remove)) {
                return $value;
            }
        }
        return [];
    }

    /**
     * 遍历子节点
     * @param $nodeId
     * @param array $node
     * @param bool $remove
     * @return array
     */
    protected function getChildrenNodeById($nodeId, array &$node, bool $remove = false): array
    {
        // 遍历节点
        foreach ($node as $nodeKey => &$nodeValue) {
            if ($nodeValue[$this->nodeKey] === $nodeId) {
                if ($remove) unset($node[$nodeKey]);
                return $nodeValue;
            }
            if ($nodeValue['children'] && $value = $this->getChildrenNodeById($nodeId, $nodeValue['children'], $remove)) {
                return $value;
            }
        }
        return [];
    }

    /**
     * 删除节点
     * @param string|int $nodeId
     * @return array
     */
    public function removeNode(string|int $nodeId): array {
        return $this->getNode($nodeId, true);
    }

    /**
     * 获取排序后的数据
     * @return array
     */
    public function getSortNode(): array
    {
        return $this->sort() -> sortNode;
    }
}
